/*
 * @Descripttion   :
 * @version        :
 * @Author         :
 * @Date           : 2025-08-11 09:49
 * @LastEditTime   : 2025-09-28 10:36
 */
/*
 * @Descripttion   :
 * @version        :
 * @Author         :
 * @Date           : 2025-07-01 09:07
 * @LastEditTime   : 2025-08-08 16:39
 */
import { gsap } from 'gsap'
import imimageUrl from '@/assets/images/fence.png'
import Overlay from './Overlay'
import store from '@/store/index.js'
export default class BoxEffect3 extends Overlay {
  constructor ({
    sandbox,
    position = { x: 0, y: 0, z: 0 },
    rotation = { x: 0, y: 0, z: 0 },
    scale = { x: 1, y: 1, z: 1 },
    color = 0x00ffff, // 0x00ffff #FF7C02 #e91010 #24ffcb
    alpha = 1.0,
    speed = 5.0,
    layers = 3,
    width = 0.5,
    useEffect = 0
  }) {
    super()
    this.sandbox = sandbox
    this.scene = sandbox.scene
    this._position = position
    this._rotation = rotation
    this._scale = scale
    this.color = color
    this.alpha = alpha
    this.speed = speed
    this.layers = layers
    this.width = 1 / width
    this.animationId = null
    this.useEffect = useEffect
    return this.initOverlay()
  }

  async initOverlay () {
    const mVertexShader = `
    varying vec2 vUv;
    varying float vIsSideFace;
    
    void main() {
        vUv = uv;
        vIsSideFace = step(0.5, 1.0 - abs(normal.y));             
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
    `
    const mFragmentShader = `
    uniform vec4 input_color;
    uniform float speed;
    uniform float layers;
    uniform float time;
    uniform float width;
    uniform sampler2D colortexture;
    uniform bool useEffect; 
    varying vec2 vUv;
    varying float vIsSideFace;
    
    void main() {
        if (vIsSideFace < 0.5) {
            discard;
        }             
        vec2 st = vUv;    
        const float PI = 3.141592653589793;
        float a =1.0;
        if (useEffect) {
          a =0.2+0.6* (0.5+0.5*sin(time* speed));
        } else {
          a=1.0;
        }
        vec4 color = texture(colortexture, st);
        gl_FragColor = color.rgba*vec4(input_color.rgb,a);
       // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
    `

    this.texture = await this.loadImageToTexture(imimageUrl)
    const material = new GC.ShaderMaterial({
      uniforms: {
        input_color: {
          value: new GC.Vector4(
            new GC.Color(this.color).r,
            new GC.Color(this.color).g,
            new GC.Color(this.color).b,
            this.alpha
          )
        },
        speed: { value: this.speed },
        layers: { value: this.layers },
        time: { value: 0 },
        width: { value: this.width },
        colortexture: {
          value: this.texture
        },
        useEffect: { value: this.useEffect }
      },
      vertexShader: mVertexShader,
      fragmentShader: mFragmentShader,
      side: GC.DoubleSide,
      transparent: true,
      depthWrite: false, // 关键设置！禁止写入深度缓冲区
      depthTest: false, // 保持深度测试启用
      alphaTest: 0.01
    })
    // material.renderOrder = 1;

    const updateMaterial = () => {
      material.uniforms.time.value += 0.01
      this.animationId = requestAnimationFrame(updateMaterial)
    }

    // 启动动画
    updateMaterial()

    // const scaleArr = Array.isArray(this._scale) ? this._scale : [this._scale, this._scale, this._scale]
    const scaleArr = [this._scale.x, this._scale.y, this._scale.z]
    const geometry = new GC.BoxGeometry(1, 1, 1)
    this.overlay = new GC.Mesh(geometry, material)
    const { x, y, z } = this._position
    this.overlay.position.set(x, y, z)
    this.overlay.rotation.set(
      GC.MathUtils.degToRad(this._rotation.x), // 将度转换为弧度
      GC.MathUtils.degToRad(this._rotation.y),
      GC.MathUtils.degToRad(this._rotation.z)
    )
    this.overlay.scale.set(...scaleArr)
    this.scene.add(this.overlay)
    return this
  }

  // 停止动画
  stopAnimation () {
    if (this.animationId) {
      cancelAnimationFrame(this.animationId)
      this.animationId = null
    }
  }

  zoomTo () {
    const box = new GC.Box3().setFromObject(this.overlay)
    const size = box.getSize(new GC.Vector3())
    const center = box.getCenter(new GC.Vector3())

    const yawDegrees = 0 // 水平旋转 180°
    const pitchDegrees = -45 // 垂直旋转角度（°）
    const distance = 4 // 注意：这里用正数，因为方向由 `direction` 决定
    const offect = new GC.Vector3(0, 5, 0)
    // 角度转弧度
    const yawRad = GC.MathUtils.degToRad(yawDegrees)
    const pitchRad = GC.MathUtils.degToRad(pitchDegrees)

    const direction = new GC.Vector3()
    direction.setFromSphericalCoords(
      1,
      Math.PI / 2 - pitchRad, // 注意：极角是 π/2 - pitch
      yawRad
    )

    const target = new GC.Vector3()
    target.copy(center).add(direction.multiplyScalar(distance))

    // 设置相机位置（在目标点后方，实现 180° 旋转）
    const cameraPos = new GC.Vector3()
    cameraPos.copy(center).add(direction.multiplyScalar(-distance)) // 反向延长

    cameraPos.add(offect)
    // 更新相机和 controls
    this.sandbox.controls.target.set(target.x, target.y, target.z)
    window.sandbox.camera.position.copy(cameraPos)
  }

  zoomToTween () {
    let yawDegrees = 180
    if (store.state.isReverse) {
      yawDegrees = 0
    }
    console.log('yawDegrees', yawDegrees)

    const box = new GC.Box3().setFromObject(this.overlay)
    const center = box.getCenter(new GC.Vector3())

    const pitchDegrees = -45 // 垂直旋转 -45°（向下看）
    const distance = 4
    const offset = new GC.Vector3(0, 5, 0)

    // 角度转弧度
    const yawRad = GC.MathUtils.degToRad(yawDegrees)
    const pitchRad = GC.MathUtils.degToRad(pitchDegrees)

    // 计算方向
    const direction = new GC.Vector3()
    direction.setFromSphericalCoords(
      1,
      Math.PI / 2 - pitchRad,
      yawRad
    )

    // 计算目标点 target
    const target = new GC.Vector3()
    target.copy(center).add(direction.multiplyScalar(distance))

    // 计算相机位置（反向延长 + 偏移）
    const cameraPos = new GC.Vector3()
    cameraPos.copy(center).add(direction.multiplyScalar(-distance)).add(offset)

    // 使用 GSAP 动画平滑过渡
    gsap.to(window.sandbox.camera.position, {
      x: cameraPos.x,
      y: cameraPos.y,
      z: cameraPos.z,
      duration: 1, // 动画时长（秒）
      ease: 'power2.inOut', // 缓动函数
      onUpdate: () => {
        // 每帧更新 controls.target（确保视角同步）
        // this.sandbox.controls.target.set(target.x, target.y, target.z);
        // this.sandbox.controls.update(); // 必须调用！
      }
      // onComplete: () => {
      //   console.log("相机动画完成");
      // }
    })

    // 使用 GSAP 动画平滑过渡
    gsap.to(window.sandbox.controls.target, {
      x: target.x,
      y: target.y,
      z: target.z,
      duration: 1, // 动画时长（秒）
      ease: 'power2.inOut' // 缓动函数
      // onComplete: () => {
      //   console.log("相机动画完成");
      // }
    })
  }

  zoomToTarget (targetPosition, targetPoint) {
    const [x, y, z] = targetPosition
    const newtargetPosition = { x, y, z }
    const [x1, y1, z1] = targetPoint
    const newtargetPoint = new GC.Vector3(x1, y1, z1)
    // 使用TWEEN动画
    new GC.TWEEN.Tween(this.sandbox.camera.position)
      .to(newtargetPosition, 1000)
      .easing(GC.TWEEN.Easing.Quadratic.Out)
      // .onUpdate(() => {
      //   this.sandbox.camera.lookAt(newtargetPoint);
      // })
      .start()

    // this.sandbox.controls.target.set(...targetPoint)
    new GC.TWEEN.Tween(this.sandbox.controls.target)
      .to(newtargetPoint, 1000)
      .easing(GC.TWEEN.Easing.Quadratic.Out)
      .start()
  }

  get modelName () {
    const filePath = this.url
    const lastSlashIndex = filePath.lastIndexOf('/')
    const fileNameWithExt = filePath.substring(lastSlashIndex + 1)

    const lastDotIndex = fileNameWithExt.lastIndexOf('.')
    return fileNameWithExt.substring(0, lastDotIndex)
  }

  loadImageToTexture (url) {
    return new Promise((resolve, reject) => {
      const image = new Image()
      image.crossOrigin = 'anonymous' // 如果需要跨域
      image.onload = () => {
        // 创建 Texture 并传入加载完成的 Image 对象
        const texture = new GC.Texture(image)
        texture.needsUpdate = true // 关键！通知纹理已更新
        resolve(texture)
      }
      image.onerror = (err) => {
        console.error('加载图片失败:', url, err)
        reject(err)
      }
      image.src = url
    })
  }
}
